<?php

namespace App\Http\Controllers\Home;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Api\HomeUserCache;
use App\Http\Controllers\Api\SendMessage;
use App\Model\HomeUserModel;
use App\Model\HomeUserScores;
use App\Model\HomeUserMemberExp;
use App\Model\HomeUserCaptcha;
use App\Model\HomeUserPasswordWrong;
use App\Http\Requests\HomeUserpasswordLogin;
use App\Http\Requests\HomeUserPhoneCaptchaLogin;
use App\Http\Controllers\Home\ShowLinksController;
use App\Http\Controllers\Api\IndexApi;
use DB;

class HomeLoginController extends Controller
{
    /**
     * 显示登录页面
     */
    public function ShowLoginPage()
    {
        // 站点信息类
        $type = new IndexApi;
        $index = new ShowLinksController;

        // 获取站点信息
        $sate = IndexApi::getSate();
        $linksArray = $index->index();

        // 返回视图层
        return view('Home.goods-login', ['sate' => $sate, 'linksArray' => $linksArray]);
    }

    /**
     * 用户密码登录信息处理
     */
    public function ValidataLogininfo(HomeUserpasswordLogin $request)
    {
        // 得到记录登录方法的实例
        $loginannal = new HomeUserCache;

        // 准备redis键名
        $userkey = 'home_user_hash_phone:'.$request->phone;

        // 查询redis是否有该用户
        $redisuser = Redis::hGetAll($userkey);

        // 判断redis中是否有该用户
        if (!$redisuser) {

            // redis中没有该用户时mysql查询该用户是否已存在
            $mysqluser = HomeUserModel::where('phone', $request->phone)->get();

            // 判断是否有该用户
            if (!isset($mysqluser[0])) {
                // redis和mysql中都没有该用户时返回错误信息
                return redirect()->route('home.login')->with('message', '未找到该用户');

            } else {
                /*mysql中有该用户时去执行登录流程*/

                // 判断是否给禁用
                $res = $this->checkPassWrongTime($mysqluser[0]->id);

                // 判断是否禁用
                if ($res === false) {
                    return redirect()->route('home.login')->with('message', '由于今天您的密码错误次数过多，将暂时冻结三十分钟');
                }

                // 哈希解密
                $bool = password_verify($request->input('password'), $mysqluser[0]->passname);


                // 判断密码是否正确
                if ($bool) {

                    // 判断是否被禁用
                    if ($mysqluser[0]->user_status > 0) {

                        // 记录并得到登录次数
                        $loginnumber = $loginannal->LoginAnnal($mysqluser[0]->id);

                        // 判断该用户登录次数是否超过15次
                        if ($loginnumber > 15) {
                            // 准备键名
                            $userkey = 'home_user_hash_phone:'.$mysqluser[0]->phone;

                            // 添加数据到redis
                            $userinfo = Redis::hMSet($userkey, [
                                'id'         => $mysqluser[0]->id,
                                'username'   => $mysqluser[0]->username,
                                'passname'   => $mysqluser[0]->password,
                                'sex'        => $mysqluser[0]->sex,
                                'pic'        => $mysqluser[0]->pic,
                                'email'      => $mysqluser[0]->email,
                                'phone'      => $mysqluser[0]->phone,
                                'user_status'=> $mysqluser[0]->user_status,
                                'member'     => $mysqluser[0]->member,
                                'created_at' => $mysqluser[0]->createtime,
                            ]);
                        }

                        // 准备登陆数据
                        $user = [
                            'id'         => $mysqluser[0]->id,
                            'username'   => $mysqluser[0]->username,
                            'sex'        => $mysqluser[0]->sex,
                            'pic'        => $mysqluser[0]->pic,
                            'email'      => $mysqluser[0]->email,
                            'member'     => $mysqluser[0]->member,
                        ];

                        // 登录成功
                        session(['Homeuser-data' => $user]);

                        //登录成功就拿到用户的UID，根据UID去查询购物车数据表，将
                        // 该用户的数据表数据遍历出来添加到该用户的redis购物车数据中

                        $uid = $user['id'];

                        $cartMysqls = DB::table('shop_goods_carts')
                                        ->select('attr_id', 'buy_num')
                                        ->where('user_id', $uid)
                                        ->get()
                                        ->toArray();

                        $session_id = session()->getId();

                        //用户购物车拼接redis中哈希的key($attr_id1, $num1, $attr_id2, $num2,...)
                        $cartKey = 'user_cart_attrid_num_hash_'.$session_id;

                        //用户购物车拼接好redis中集合的key($attr_id1, $attr_id2,...)
                        $cartGoods = 'user_cart_attrid_set_'.$session_id;

                        //拼接好用户已经添加进购物车的商品属性的哈希的key('brand', $brand, 'name', $name, 'desc', $desc, 'color', $color, 'size', $size, 'price', $price, 'pic', $pic)
                        // $cartGoodsInfoKey = 'user_cart_attrid_detail_hash_'.$session_id.'_'.$attr_id;

                        foreach ($cartMysqls as $v) {
                            //redis中有这个属性id就加数量
                            if (Redis::hExists($cartKey, $v->attr_id)) {
                                Redis::hIncrby($cartKey, $v->attr_id, $v->buy_num);
                            } else {
                                //redis中没有该商品直接设置键和值
                                Redis::hMSet($cartKey, $v->attr_id, $v->buy_num);
                                //顺便把属性id加入集合
                                Redis::sAdd($cartGoods, $v->attr_id);
                            }
                        }

                        //遍历完后就把该用户的购物车表数据清空
                        DB::table('shop_goods_carts')->where('user_id', $uid)
                                                     ->delete();

                        return redirect()->route('Home.index');
                    }
                    // 用户已被冻结
                    return redirect()->route('home.login')->with('message', '您的账号已被冻结，请联系管理员');
                }

                // 记录密码错误状态
                $this->recordPassWrongTime($mysqluser[0]->id);

                // 返回提示信息
                return redirect()->route('home.login')->with('message', '密码错误，还剩'.$res.'次机会');
            }
        } else {
            /*redis中查到该用户时执行登录流程*/

            // 查询登录错误次数
            $res = $this->checkPassWrongTime($redisuser['id']);

            // 判断是否禁用
            if ($res === false) {
                return redirect()->route('home.login')->with('message', '由于今天您的密码错误次数过多，将暂时冻结三十分钟');
            }

            // 哈希解密
            $bool = password_verify($request->input('password'), $redisuser['passname']);

            // 判断密码是否正确
            if ($bool) {

                // 判断是否被禁用
                if ($redisuser['user_status'] > 0) {
                    // 记录并得到登录次数
                    $loginnumber = $loginannal->LoginAnnal($redisuser['id']);

                    // 准备登陆数据
                    $user = [
                        'id'         => $redisuser['id'],
                        'username'   => $redisuser['username'],
                        'sex'        => $redisuser['sex'],
                        'pic'        => $redisuser['pic'],
                        'email'      => $redisuser['email'],
                        'member'     => $redisuser['member'],
                    ];

                    // 登录成功
                    session(['Homeuser-data' => $user]);

                    //登录成功就拿到用户的UID，根据UID去查询购物车数据表，将
                    // 该用户的数据表数据遍历出来添加到该用户的redis购物车数据中

                    $uid = $user['id'];

                    $cartMysqls = DB::table('shop_goods_carts')
                                    ->select('attr_id', 'buy_num')
                                    ->where('user_id', $uid)
                                    ->get()
                                    ->toArray();

                    $session_id = session()->getId();

                    //用户购物车拼接redis中哈希的key($attr_id1, $num1, $attr_id2, $num2,...)
                    $cartKey = 'user_cart_attrid_num_hash_'.$session_id;

                    //用户购物车拼接好redis中集合的key($attr_id1, $attr_id2,...)
                    $cartGoods = 'user_cart_attrid_set_'.$session_id;

                    //拼接好用户已经添加进购物车的商品属性的哈希的key('brand', $brand, 'name', $name, 'desc', $desc, 'color', $color, 'size', $size, 'price', $price, 'pic', $pic)
                    // $cartGoodsInfoKey = 'user_cart_attrid_detail_hash_'.$session_id.'_'.$attr_id;

                    foreach ($cartMysqls as $v) {
                        //redis中有这个属性id就加数量
                        if (Redis::hExists($cartKey, $v->attr_id)) {
                            Redis::hIncrby($cartKey, $v->attr_id, $v->buy_num);
                        } else {
                            //redis中没有该商品直接设置键和值
                            Redis::hMset($cartKey, $v->attr_id, $v->buy_num);
                            //顺便把属性id加入集合
                            Redis::sAdd($cartGoods, $v->attr_id);
                        }
                    }

                    //遍历完后就把该用户的购物车表数据清空
                    DB::table('shop_goods_carts')->where('user_id', $uid)
                                                 ->delete();


                    return redirect()->route('Home.index');
                }
                // 用户已被冻结
                return redirect()->route('home.login')->with('message', '您的账号已被冻结，请联系管理员');
            }

            // 记录密码错误状态
            $this->recordPassWrongTime($redisuser['id']);

            // 返回提示信息
            return redirect()->route('home.login')->with('message', '密码错误，还剩'.$res.'次机会');
        }

        // 返回错误信息
        return redirect()->route('home.login')->with('message', '服务器繁忙，请稍后再试!');
    }



    /**
     * 短信验证登录处理
     */
    public function PhoneCaptchaLogin(HomeUserPhoneCaptchaLogin $request)
    {
        // 查询该用户的验证码
        $captcha = HomeUserCaptcha::where([
            ['captchaIndex', '=', $request->phone],
            ['type', '=', 2],
          ])
          ->orderBy('validperiod', 'desc')
          ->first();

        // 判断该用户是否非法
        if(empty($captcha)) {
            return redirect()->route('home.login')->with('message', '服务器繁忙请重试!');
        }

        // 判断验证码是否超时
        if ($captcha->validperiod < time()) {
            $result = HomeUserCaptcha::where([
                ['captchaIndex', '=',$request->phone],
                ['type', '=', 2],
            ])->delete();
            return redirect()->route('home.login')->with('message', '验证码超时，请重新获取!');
        }

        // 判断是否验证成功
        if ($request->code == $captcha->captcha) {

            // 删除使用过的密码
            $result = HomeUserCaptcha::where([
                ['captchaIndex', '=',$request->phone],
                ['type', '=', 2],
            ])->delete();
            // 得到记录登录方法的实例
            $loginannal = new HomeUserCache;

            // 准备redis键名
            $userkey = 'home_user_hash_phone:'.$request->phone;

            // 查询redis是否有该用户
            $redisuser = Redis::hGetAll($userkey);

            // 判断redis中是否有该用户
            if (!$redisuser) {

                // redis中没有该用户时mysql查询该用户是否已存在
                $mysqluser = HomeUserModel::where('phone', $request->phone)->get();

                // 判断是否有该用户
                if (!isset($mysqluser[0])) {
                    // redis和mysql中都没有该用户时返回错误信息
                    return redirect()->route('home.login')->with('message', '未找到该用户');

                } else {
                    /*mysql中有该用户时去执行登录流程*/

                    // 判断是否被禁用
                    $res = $this->checkPassWrongTime($mysqluser[0]->id);

                    // 判断是否禁用
                    if ($res === false) {
                        return redirect()->route('home.login')->with('message', '由于今天您的密码错误次数过多，将暂时冻结三十分钟');
                    }


                    // 判断是否被禁用
                    if ($mysqluser[0]->user_status > 0) {

                        // 记录并得到登录次数
                        $loginnumber = $loginannal->LoginAnnal($mysqluser[0]->id);

                        // 判断该用户登录次数是否超过15次
                        if ($loginnumber > 15) {
                            // 准备键名
                            $userkey = 'home_user_hash_phone:'.$mysqluser[0]->phone;

                            // 添加数据到redis
                            $userinfo = Redis::hMSet($userkey, [
                                'id'         => $mysqluser[0]->id,
                                'username'   => $mysqluser[0]->username,
                                'passname'   => $mysqluser[0]->password,
                                'sex'        => $mysqluser[0]->sex,
                                'pic'        => $mysqluser[0]->pic,
                                'email'      => $mysqluser[0]->email,
                                'phone'      => $mysqluser[0]->phone,
                                'user_status'=> $mysqluser[0]->user_status,
                                'member'     => $mysqluser[0]->member,
                                'created_at' => $mysqluser[0]->createtime,
                            ]);
                        }

                        // 准备登陆数据
                        $user = [
                            'id'         => $mysqluser[0]->id,
                            'username'   => $mysqluser[0]->username,
                            'sex'        => $mysqluser[0]->sex,
                            'pic'        => $mysqluser[0]->pic,
                            'email'      => $mysqluser[0]->email,
                            'member'     => $mysqluser[0]->member,
                        ];

                        // 登录成功
                        session(['Homeuser-data' => $user]);
                        return redirect()->route('Home.index');
                    }
                    // 被禁用
                    return redirect()->route('home.login')->with('message', '您的账号已被冻结，请联系管理员');
                }
            } else {
                /*redis中查到该用户时执行登录流程*/

                // 查询登录错误次数
                $res = $this->checkPassWrongTime($redisuser['id']);

                // 判断是否禁用
                if ($res === false) {
                    return redirect()->route('home.login')->with('message', '由于今天您的密码错误次数过多，将暂时冻结三十分钟');
                }

                // 判断是否被禁用
                if ($redisuser['user_status'] > 0) {
                    // 记录并得到登录次数
                    $loginnumber = $loginannal->LoginAnnal($redisuser['id']);

                    // 准备登陆数据
                    $user = [
                        'id'         => $redisuser['id'],
                        'username'   => $redisuser['username'],
                        'sex'        => $redisuser['sex'],
                        'pic'        => $redisuser['pic'],
                        'email'      => $redisuser['email'],
                        'member'     => $redisuser['member'],
                    ];

                    // 登录成功
                    session(['Homeuser-data' => $user]);
                    return redirect()->route('Home.index');
                }
                // 删除该用户使用过的验证码
                $result = HomeUserCaptcha::where([
                    ['captchaIndex', '=',$request->phone],
                    ['type', '=', 2],
                ])->delete();
                // 用户已被冻结
                return redirect()->route('home.login')->with('message', '您的账号已被冻结，请联系管理员');
            }
        } else {
            // 验证码错误
            return redirect()->route('home.login')->with('message', '验证码错误!');
        }
        // 返回错误信息
        return redirect()->route('home.login')->with('message', '服务器繁忙，请稍后再试!');
    }

    /**
     * 记录密码错误信息
     * data uid
     */
    protected function recordPassWrongTime($id)
    {

        // ip2long()函数可以将IP地址转换成数字
        $ip = ip2long( $_SERVER['REMOTE_ADDR'] );

        if ($ip < 0) {
            $ip = sprintf('%u', $ip);
        }

        // 准备密码错误记录时间
        $time = time();

        // 插入数据
        HomeUserPasswordWrong::insert([
            'user_id'           => $id,
            'ipaddress'         => $ip,
            'logintime'         => $time,
            'pass_wrong_status' => 2,
        ]);
    }

    /**
     * data phone[登录手机号] min[多久内登录] wtime[登陆次数限制]
     * @return wrongTime[错误次数] false
     */
    protected function checkPassWrongTime($id, $min=30, $wTime=3)
    {
        // 准备对比时间
        $time = time();
        // 准备多久前的世界
        $prevTime = time() - $min*60;

        //用户所在登录ip
        $ip = ip2long( $_SERVER['REMOTE_ADDR'] );

        if ($ip < 1) {
            $ip = sprintf('%u', $ip);
        }

        // 查找用户登录错误信息
        $data = HomeUserPasswordWrong::whereBetween('logintime', [$prevTime, $time])
            ->where([
              ['user_id', '=', $id],
              ['pass_wrong_status', '=', 2,],
              ['ipaddress', '=', $ip],
            ])
            ->get();

            //统计错误次数
            $wrongTime = count($data);

            //判断错误次数是否超过限制次数
            if ( $wrongTime > $wTime ) {
                // 返回false
                return false;
            }

            // 统计剩下错误次数
            $wrongTime = 3 - $wrongTime;

            // 返回次数
            return $wrongTime;
    }

    /**
     * 发送手机验证码
     * data $phone $type[1:注册状态码 2:登录状态码 3:修改密码状态码]
     * @return status validperiod message code type
     */
    public function LoginValidata(Request $request)
    {

      // 查询该用户的验证码
      $captcha = HomeUserCaptcha::where([
          ['captchaIndex', '=', $request->phone],
          ['type', '=', 2],
        ])
        ->orderBy('validperiod', 'desc')
        ->first();

        if ($captcha) {

            // 判断是否手贱
            if ($captcha->validperiod > time()) {
                return 403;
            }
        }

        // 获取对象
        $send = new SendMessage;

        // 调用方法发送验证码
        $result = $send->SendPhoneMessage($request->phone, 2);

        // 判断是否发送成功
        if ($result['status'] == "200") {
            // 成功时把验证信息添加到表内
            HomeUserCaptcha::insert([
                'captchaIndex'=> $request->phone,
                'captcha'     => $result['captcha'],
                'validperiod' => $result['validperiod'],
                'type'        => $result['type'],
            ]);

        }

        // 返回状态码
        return $result['status'];
    }

    /**
     * 判断用户验证码是否正确
     */
    public function ValidataLogin(Request $request)
    {
        // 查询该用户的验证码
        $captcha = HomeUserCaptcha::where([
            ['captchaIndex', '=', $request->phone],
            ['type', '=', 2],
          ])
          ->orderBy('validperiod', 'desc')
          ->first();

        // 判断该用户是否有获取验证码s
        if (!$captcha) {
            // 验证成功
            return 500;
        }

        // 判断验证码是否超时
        if ($captcha->validperiod < time()) {
            return 403;
        }

        // 判断是否验证成功
        if ($request->code == $captcha->captcha) {
            // 验证成功
            return 200;
        }
        // 验证码错误
        return 500;
    }

    // 退出登录
    public function LoginOut(Request $request)
    {
        $request->session()->forget('Homeuser-data');
        return redirect()->route('home.login');
    }

}
